#ifndef RTE_FX3U_ZT_RETAIN_FRAM_H
#define RTE_FX3U_ZT_RETAIN_FRAM_H


class retain_fram : public mem_block {
public:
    SPIClass spi;
    u8 cs;

    retain_fram(uint32_t ba, uint32_t bb, SPIClass &spi_, u8 cs_) {
        adr[0] = ba;
        adr[1] = bb;
        spi = spi_;
        cs = cs_;
        spi.begin();
        // set the cs as an output:
        pinMode(cs, OUTPUT);

        digitalWrite(cs, HIGH); //Disable Chip
    }

    void begin(const char *name, int sz) override {}

    void Remove(int i) override {
        //not use
    }

    void Write(unsigned char block, unsigned int start, void *pVoid, unsigned int len) override {
        uint32_t FRAM_address = adr[block] + start;
        uint8_t *FRAM_wr_data_ptr = (uint8_t *) pVoid;
        // If write pointer is NULL, return
        if (FRAM_wr_data_ptr == NULL_PTR)
            return;

        // F-RAM WRITE ENABLE COMMAND
        digitalWrite(cs, LOW);  //chip select
        spi.transfer(WREN);    //transmit write enable opcode
        digitalWrite(cs, HIGH); //release chip, signal end transfer

        // F-RAM WRITE OPERATION
        digitalWrite(cs, LOW);                   //chip select
        spi.transfer(WRITE);                    //transmit write opcode
        spi.transfer(MSB_ADDR_BYTE(FRAM_address));  //send MSByte address first
        spi.transfer(LSB_ADDR_BYTE(FRAM_address));  //send LSByte address

        // Data byte transmission
        for (int i = 0; i < len; i++)
            spi.transfer((uint8_t) (FRAM_wr_data_ptr[i]));        //send 1 byte data at a time

        digitalWrite(cs, HIGH);                  //release chip, signal end of transfer
    }

    int Read(u8 block, unsigned int start, unsigned int len, void *pVoid) override {
        uint32_t FRAM_address = adr[block] + start;
        uint8_t *FRAM_rd_data_ptr = (uint8_t *) pVoid;

        digitalWrite(cs, LOW);                     //chip select
        spi.transfer(READ);                       //transmit read opcode
        spi.transfer(MSB_ADDR_BYTE(FRAM_address));  //send MSByte address first
        spi.transfer(LSB_ADDR_BYTE(FRAM_address));  //send LSByte address

        for (int i = 0; i < len; i++)
            FRAM_rd_data_ptr[i] = spi.transfer(0xFF);  //get all the data bytes from F-RAM

        digitalWrite(cs, HIGH);  //release chip, signal end of transfer
        return 0;
    }

    int Shutdown() override {
        return 0;
    }

    int begin(byte *name, byte name_sz, uint32_t start_address, uint32_t data_len) override {
        return 0;
    }

    int begin_read(byte *name, byte name_sz, uint32_t start_address, uint32_t data_len) {
        return 0;
    }

    const char *name() override {
        return "Fram";
    }

private:
    uint32_t adr[2]{};
};

#endif //RTE_FX3U_ZT_RETAIN_FRAM_H
